package tetris.game.view;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import tetris.game.model.Block;
import tetris.game.model.Field;
import tetris.game.model.GameField;
import android.opengl.GLSurfaceView.Renderer;
import android.opengl.GLU;

public class TetrisGLRenderer implements Renderer {

	private float screen_width;
	private float screen_height;

	private FloatBuffer backgroundVB;
	private Quad quad;
	private Field[][] gameField;
	private Block upcomingBlock;

	
	public void setGameField(Field[][] field) {
		this.gameField = field;
	}
	
	public void setUpcomingBlock(Block upcomingBlock) {
		this.upcomingBlock = upcomingBlock;
	}
	
	
	/**
	 * Draws a black background for the game
	 */
	private void initBackground() {
		float bgCoords[] = { 
				0, 0, 0, 											// bottom left
				0, screen_height, 0, 								// top left
				(screen_height / 20) * 10, screen_height, 0, 		// top right
				(screen_height / 20) * 10, 0, 0 					// bottom right
		};

		// initialize vertex Buffer for triangle
		ByteBuffer vbb = ByteBuffer.allocateDirect(bgCoords.length * 4);
		vbb.order(ByteOrder.nativeOrder());	// use the device hardware's native byte order
		backgroundVB = vbb.asFloatBuffer(); 	// create a floating point buffer from the ByteBuffer
		backgroundVB.put(bgCoords); 			// add the coordinates to the FloatBuffer
		backgroundVB.position(0); 			// set the buffer to read the first coordinate
	}
	
	
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
		// reset background color
		gl.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
      }

	
	public void onDrawFrame(GL10 gl) {
		gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);

		// set black game background
		gl.glColor4f(0, 0, 0, 1.0f);
		initBackground();
		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, backgroundVB);
		gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, 4);

		
		// reads gamefield and draws the blocks
		quad = new Quad(gl, screen_width, screen_height);
		for (int y = 0; y < gameField.length; y++) {
			for (int x = 0; x < gameField[y].length; x++) {
				
				switch(gameField[y][x].getColor()) {
					case RED: 		gl.glColor4f(1, 0, 0, 1); quad.drawQuad(x, GameField.FIELD_HEIGHT-y-1); break;
					case YELLOW:	gl.glColor4f(1, 1, 0, 1); quad.drawQuad(x, GameField.FIELD_HEIGHT-y-1); break;
					case BLUE:		gl.glColor4f(0, 0, 1, 1); quad.drawQuad(x, GameField.FIELD_HEIGHT-y-1); break;
					case GREEN:		gl.glColor4f(0, 1, 0, 1); quad.drawQuad(x, GameField.FIELD_HEIGHT-y-1); break;
					case LIGHT_GREEN: gl.glColor4f(0, 1, 1, 1); quad.drawQuad(x, GameField.FIELD_HEIGHT-y-1); break;
					case ORANGE: gl.glColor4f(1, 0.55f, 0, 1); quad.drawQuad(x, GameField.FIELD_HEIGHT-y-1); break;
					case VIOLET: gl.glColor4f(0.75f, 0, 1, 1); quad.drawQuad(x, GameField.FIELD_HEIGHT-y-1); break;
				}
			}
		}
		
		drawUpcomingBlock(gl);
	}

	
	public void onSurfaceChanged(GL10 gl, int width, int height) {
		screen_width = width;
		screen_height = height;

		// the real size of the screen
		gl.glViewport(0, 0, width, height);

		// the wanted size of the screen
		gl.glMatrixMode(GL10.GL_PROJECTION);
		gl.glLoadIdentity();
		GLU.gluOrtho2D(gl, 0, width, 0, height);   // orthogonal projection
	}
	
	
	/**
	 * draws the next upcoming block in the top right corner of the screen
	 * @param gl
	 */
	public void drawUpcomingBlock(GL10 gl) {

		// switch to the right color for the upcoming block
		switch(upcomingBlock.getBlockColor()) {
			case RED: 		gl.glColor4f(1, 0, 0, 1.0f); break;
			case YELLOW: 	gl.glColor4f(1, 1, 0, 1.0f); break;
			case BLUE:		gl.glColor4f(0, 0, 1, 1.0f); break;
			case GREEN:		gl.glColor4f(0, 1, 0, 1.0f); break;
			case LIGHT_GREEN: gl.glColor4f(0, 1, 1, 1); break;
			case ORANGE: gl.glColor4f(1, 0.55f, 0, 1); break;
			case VIOLET: gl.glColor4f(0.75f, 0, 1, 1); break;
		}
		
		// draw the upcoming block in the top right corner of the screen
		switch(upcomingBlock.getBlockType()) {
			case I:
				if(upcomingBlock.getRotation() % 180 == 0) {
					quad.drawQuad(11, 18);
					quad.drawQuad(11, 17);
					quad.drawQuad(11, 16);
					quad.drawQuad(11, 15);			
					break;
				}
				else {
					quad.drawQuad(10, 18);
					quad.drawQuad(11, 18);
					quad.drawQuad(12, 18);
					quad.drawQuad(13, 18);			
					break;
				}
			case J:
				if(upcomingBlock.getRotation() == 0) {
					quad.drawQuad(12, 18);
					quad.drawQuad(12, 17);
					quad.drawQuad(12, 16);
					quad.drawQuad(11, 16);
					break;
				}
				else if(upcomingBlock.getRotation() == 90) {
					quad.drawQuad(11, 18);
					quad.drawQuad(11, 17);
					quad.drawQuad(12, 17);
					quad.drawQuad(13, 17);
					break;
				}
				else if(upcomingBlock.getRotation() == 180) {
					quad.drawQuad(12, 18);
					quad.drawQuad(11, 18);
					quad.drawQuad(11, 17);
					quad.drawQuad(11, 16);
					break;
				}
				else {
					quad.drawQuad(11, 17);
					quad.drawQuad(12, 17);
					quad.drawQuad(13, 17);
					quad.drawQuad(13, 18);
					break;
				}
			case L:
				if(upcomingBlock.getRotation() == 0) {
					quad.drawQuad(11, 18);
					quad.drawQuad(11, 17);
					quad.drawQuad(11, 16);
					quad.drawQuad(12, 16);
					break;
				}
				else if(upcomingBlock.getRotation() == 90) {
					quad.drawQuad(11, 17);
					quad.drawQuad(11, 18);
					quad.drawQuad(12, 18);
					quad.drawQuad(13, 18);
					break;
				}
				else if(upcomingBlock.getRotation() == 180) {
					quad.drawQuad(11, 18);
					quad.drawQuad(12, 18);
					quad.drawQuad(12, 17);
					quad.drawQuad(12, 16);
					break;
				}
				else {
					quad.drawQuad(11, 17);
					quad.drawQuad(12, 17);
					quad.drawQuad(13, 17);
					quad.drawQuad(13, 18);
					break;
				}
			case O:
				quad.drawQuad(11, 18);
				quad.drawQuad(11, 17);
				quad.drawQuad(12, 18);
				quad.drawQuad(12, 17);
				break;
			case S:
				if(upcomingBlock.getRotation() % 180 == 0) {
					quad.drawQuad(12, 18);
					quad.drawQuad(13, 18);
					quad.drawQuad(11, 17);
					quad.drawQuad(12, 17);
					break;
				}
				else {
					quad.drawQuad(11, 18);
					quad.drawQuad(11, 17);
					quad.drawQuad(12, 17);
					quad.drawQuad(12, 16);
					break;
				}
			case T:
				if(upcomingBlock.getRotation() == 0) {
					quad.drawQuad(12, 17);
					quad.drawQuad(11, 18);
					quad.drawQuad(12, 18);
					quad.drawQuad(13, 18);
					break;
				}
				else if(upcomingBlock.getRotation() == 90) {
					quad.drawQuad(12, 18);
					quad.drawQuad(12, 17);
					quad.drawQuad(12, 16);
					quad.drawQuad(11, 17);
					break;
				}
				else if(upcomingBlock.getRotation() == 180) {
					quad.drawQuad(11, 17);
					quad.drawQuad(12, 17);
					quad.drawQuad(13, 17);
					quad.drawQuad(12, 18);
					break;
				}
				else {
					quad.drawQuad(11, 18);
					quad.drawQuad(11, 17);
					quad.drawQuad(11, 16);
					quad.drawQuad(12, 17);
					break;
				}
			case Z:
				if(upcomingBlock.getRotation() % 180 == 0) {
					quad.drawQuad(11, 18);
					quad.drawQuad(12, 18);
					quad.drawQuad(12, 17);
					quad.drawQuad(13, 17);
					break;
				}
				else {
					quad.drawQuad(12, 18);
					quad.drawQuad(12, 17);
					quad.drawQuad(11, 17);
					quad.drawQuad(11, 16);
					break;
				}
			default: System.out.println("no block");
		}
	}
}